package advanced;


import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * 解析 xml文件
 * <p>
 * <p>
 * 可扩展标记语言，作为数据的一种存储格式后用于存储软件的参数，程序解析此配置文件
 * 就可以达到不用改代码就能更改程序的目的
 * <p>
 * 1. 通常使用sax 流解析
 * 2. 还有dom 解析
 */
public class L_ParseXML {
    public static void main(String[] args) {
        //创建解析工厂
        SAXParserFactory factory = SAXParserFactory.newInstance();
        //从解析工厂获取sax解析器
        try {
            SAXParser saxParser = factory.newSAXParser();
            //3. 加载需要解析的文档处理器 这个处理器需要自己编写
            PersonXMLParser xmlParser = new PersonXMLParser();

            //4. 解析文档
            //解析
            //通过当前线程的上下文来找到相对位置的xml目标文件，以流的形式 路径是从classpath开始计算的
            InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("advanced/person.xml");
            saxParser.parse(inputStream, xmlParser);
            //5. 获取解析后的数据
            List<Person> persons = xmlParser.getResults();
            for (Person p : persons) {
                System.out.println(p.toString());
            }

        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            System.out.println("解析错误");
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

class PersonXMLParser extends DefaultHandler {
    private List<Person> persons;
    private Person person;
    private String tag;

    public PersonXMLParser() {

    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        String contents = new String(ch, start, length).trim();
        if (tag != null) {
            if (tag.equals("name")) {
                person.setName(contents.toString());
            } else if (tag.equals("age")) {
                if (contents.length() > 0)
                    person.setAge(Integer.valueOf(contents));
            }
        }
    }

    @Override
    public void startDocument() throws SAXException {
        //初始化容器,存储解析后的数据
        persons = new ArrayList<>();
    }


    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if (qName != null) {
            tag = qName;//存储标签名
            if (qName.equals("person")) {
                person = new Person();
            }
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if (qName != null) {
            if (qName.equals("person")) {
                persons.add(person);
            }
        }
        tag = null;
    }

    public List<Person> getResults() {
        return persons;
    }
}

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}